const fs = require('fs-extra')
const path = require('path')
const inquirer = require('inquirer')
const fetch = require('node-fetch')
const spinner = require('ora')()
const download = require('download-git-repo')
const execa = require('execa')
const chalk = require('chalk')
const logSymbols = require('log-symbols')

const { 
  author, 
  clearScreen, 
  hasYarn 
} = require('./util')
const { 
  handlePresets, 
  presets, 
  presetNameList 
} = require('./preset')
  
let binPath = 'npm'
const optsCollection = {
	projectName: '',
	dir: '',
	frame: '',
	style: '',
	tpl: ''
}

async function handleManually (optsCollection) {
	const { frame, style } = await inquirer.prompt([
		{
			type: 'list',
			name: 'frame',
			message: '请选择开发框架',
			choices: [
				{ name: 'Vue', value: 'vue' },
				{ name: 'React', value: 'react' }
			]
		},
		{
			type: 'list',
			name: 'style',
			message: '请选择CSS预处理器',
			choices: [
				{ name: 'Sass', value: 'saas' }
			]
		}
	])
	Object.assign(optsCollection, { frame, style })

	let repos
	spinner.start('正在获取仓库...')
	if (frame === 'vue') {
		repos = await fetch(`https://api.github.com/users/${author}/repos`)
	}
	spinner.stop()
	const tpls = await repos.json()
	const { tpl } = await inquirer.prompt([
		{
			type: 'list',
			name: 'tpl',
			message: '请选择模板',
			choices: tpls.map(item => item.name)
		}
	])
	Object.assign(optsCollection, { tpl })
}

async function combo() {
  await handleManually(optsCollection)
  await handlePresets(optsCollection)
  fs.emptyDirSync(optsCollection.dir)
	clearScreen()
}

module.exports = async (projectName, mapOption) => {
  const { manually, force } = mapOption
	Object.assign(optsCollection, {
		projectName,
		dir: path.resolve(process.cwd(), projectName)
	})

	if (fs.existsSync(optsCollection.dir) && !force) {
		const { action } = await inquirer.prompt([
			{
				type: 'list',
				name: 'action',
				message: `${optsCollection.projectName}目录已存在`,
				choices: [
					{ name: '清空该目录', value: 'clean' },
					{ name: '另建目录', value: 'new' }
				]
			}
		])
		if (action === 'new') {
			const { newProjectName } = await inquirer.prompt([
				{
					type: 'input',
					name: 'newProjectName',
					message: '请输入项目名称',
					validate (input) {
						if (!input) {
							return '项目名不能为空！'
						}
						if (fs.existsSync(input)) {
							return '当前目录已经存在，请更换名称！'
						}
						return true
					}
				}
			])
			Object.assign(optsCollection, {
				projectName: newProjectName,
				dir: path.resolve(process.cwd(), newProjectName)
			})
		}
	}	

	if (!manually && presets.length) {
		const { curPreset } = await inquirer.prompt([
			{
				type: 'list',
				name: 'curPreset',
				message: '请选择预设',
				choices: [ ...presetNameList, 'manually' ]
			}
		])
		if (curPreset === 'manually') {
			await combo()
		} else {
      spinner.start('正在拉取模板...')
      const { tpl } = presets.find(item => curPreset === item.name)
      const { dir, projectName } = optsCollection 
			download(`github:${author}/${tpl}`, projectName, async err => {
				if (err) {
          process.exit()
        }
        spinner.stop()
        console.log(logSymbols.success,'模板下载完成！')
        const isYarn = hasYarn()
        binPath = isYarn ? 'yarn' : binPath
        const { isInstall } = await inquirer.prompt([
          {
            type: 'input',
            name: 'isInstall',
            message: '是否安装依赖？(Y/N)'
          }
        ])
        if (isInstall && isInstall.toLowerCase() === 'y') {
          execa.sync(binPath, ['install'], { cwd: dir, stdio: 'inherit' })
          clearScreen()
          console.log(
            `> Run:\n\n` +
            chalk.cyan(` ${chalk.gray('$')} cd ${projectName}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn serve' : 'npm run serve'}`)
          )
        }else {
          clearScreen()
          console.log(
            `> Run:\n\n` +
            chalk.cyan(` ${chalk.gray('$')} cd ${projectName}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn install' : 'npm run install'}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn serve' : 'npm run serve'}`)
          )
        }
        
			})
		}
	} else {
		await combo()
	}

}